
<!DOCTYPE html>
<!--[if IEMobile 7 ]><html class="no-js iem7"><![endif]-->
<!--[if lt IE 9]><html class="no-js lte-ie8"><![endif]-->
<!--[if (gt IE 8)|(gt IEMobile 7)|!(IEMobile)|!(IE)]><!--><html class="no-js"><!--<![endif]-->
<head>
  <meta charset="utf-8">
  <title>
    
  front-end - LZH-DEV-TECH-SHARE
  

  </title>
  <meta name="author" content="">
  <meta name="description" content="">

  <meta name="HandheldFriendly" content="True">
  <meta name="MobileOptimized" content="320">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  
  <link href="asset/css/screen.css" media="screen, projection" rel="stylesheet" type="text/css">
  <link href="atom.xml" rel="alternate" title="LZH-DEV-TECH-SHARE" type="application/atom+xml">
  <script src="asset/js/modernizr-2.0.js"></script>
  <script src="asset/js/jquery.min.js"></script>
  <script src="asset/highlightjs/highlight.pack.js"></script>
  <link href="asset/highlightjs/styles/solarized_light.css" media="screen, projection" rel="stylesheet" type="text/css">
  <script>hljs.initHighlightingOnLoad();</script>

  <style type="text/css">
  .cat-children-p{ padding: 6px 0px;}
  .hljs{background: none;}
  </style>
  <script type="text/javascript">
  var isAddSildbar = true;
  </script>
  <script src="asset/js/octopress.js" type="text/javascript"></script>
</head>
<script type="text/javascript">
//链接新开窗口
function addBlankTargetForLinks () {
  $('a[href^="http"]').each(function(){
      $(this).attr('target', '_blank');
  });
}
$(document).ready(function(event) {
  addBlankTargetForLinks();
});
</script>
<body   >
  <header role="banner"><hgroup>
  <h1><a href="index.html">LZH-DEV-TECH-SHARE</a></h1>
  
    <h2></h2>
  
</hgroup>

</header>
  <nav role="navigation"><ul class="subscription" data-subscription="rss">
  <li><a href="atom.xml" rel="subscribe-rss" title="subscribe via RSS">RSS</a></li>
  
</ul>
  
<form action="http://google.com/search" method="get">
  <fieldset role="search">
    <input type="hidden" name="q" value="site:" />
    <input class="search" type="text" name="q" results="0" placeholder="Search"/>
  </fieldset>
</form>
  
<ul class="main-navigation">

  <li id=""><a target="self" href="index.html">Home</a></li>

  <li id=""><a target="_self" href="archives.html">Archives</a></li>

</ul>

</nav>
  <div id="main">
    <div id="content"> 
<div class="blog-index">

	<article>
		 <header>
		  	<h1 class="entry-title"><a href="15410718240579.html">如何使用PM2进程管理器, 守护java进程</a></h1>
			<p class="meta"><time datetime="2018-11-01T19:30:24+08:00" 
			pubdate data-updated="true">2018/11/1</time></p>
		 </header>
	  	<div class="entry-content">
		  	
		  	<blockquote>
<p>java程序的进程管理一直是个业界关注的问题, 以往我们可能使用linux开机启动配置的方式来开机启动java程序, 或者依赖于 runit, supervisor等工具来进行java进程的守护, 今天我们来介绍的是一种更加方便的方式, 它就是PM2</p>
</blockquote>

<h2 id="toc_0">回顾</h2>

<p>前文 [PM2使用详解] 中我们可以看到, 使用pm2, 运行一个node程序及其简单, 命令如下: </p>

<pre><code class="language-shell">pm2 start server.js --name=knowledge -i max 
</code></pre>

<p>可以直接运行 js 伺服程序, 并根据及其的cpu核数, 来创建集群.<br/>
这是因为 pm2 是基于node开发的, 于是可以直接执行 js 伺服程序.</p>

<p>那么如何运行java程序呢, 问题就来了.</p>

<h2 id="toc_1">新知识点</h2>

<h3 id="toc_2">Ecosystem File</h3>

<p>这是用来描述pm2如何部署应用的配置文件, 直译过来, 是<code>生态系统文件</code>.<br/>
我们可以通过:</p>

<pre><code class="language-shell">pm2 init
</code></pre>

<p>来创建这个生态系统文件, 名为<code>ecosystem.config.js</code>, 内容如下:</p>

<pre><code class="language-javascript">module.exports = {
  apps : [{
    name: &quot;app&quot;,
    script: &quot;./app.js&quot;,
    env: {
      NODE_ENV: &quot;development&quot;,
    },
    env_production: {
      NODE_ENV: &quot;production&quot;,
    }
  }]
}
</code></pre>

<p>我们可以看出, 这个配置文件可以支持配置多个应用来运行, 其导出的根是个对象, 对象中apps就是我们要部署的应用们, 每一个对象就是我们要部署的一个应用,单个应用的配置结构类似于:</p>

<pre><code class="language-javascript">{
    name: &quot;app&quot;,
    script: &quot;./app.js&quot;,
    env: {
      NODE_ENV: &quot;development&quot;,
    },
    env_production: {
      NODE_ENV: &quot;production&quot;,
    }
}
</code></pre>

<p>这个对象中的每个选项是一个应用运行的options, 要获取其详细的配置可以<a href="https://pm2.io/doc/en/runtime/reference/ecosystem-file/#apps-options">查看这里</a><br/>
其实pm2 还支持运行 配置文件, 其配置文件格式为 json, 基本格式如图.</p>

<pre><code class="language-javascript">{
    &quot;name&quot;: &quot;my-server&quot;,
    &quot;script&quot;: &quot;/usr/bin/java&quot;,
    &quot;args&quot;: [
        &quot;-jar&quot;,
        &quot;server.jar&quot;
    ],
    &quot;exec_interpreter&quot;: &quot;&quot;,
    &quot;exec_mode&quot;: &quot;fork&quot;
}
</code></pre>

<p>怎么样, 有没感觉上面说的 js 对象的结构和 下面的 json 很像, 没错, 我们可以使用json文件来做单个应用的运行配置描述文件, 其中的属性和前述的 <a href="https://pm2.io/doc/en/runtime/reference/ecosystem-file/#apps-options">单个应用运行的options</a> 是完全一致的, 然后运行单个应用, 这个过程中根本不用考虑前面所说的<code>生态系统文件</code>.</p>

<h3 id="toc_3">注意</h3>

<p>在上述的最后json配置文件例子中, 我们 script 运行了 java 程序, 在 args 中, 指定了运行的jar包, 等信息.</p>

<h3 id="toc_4">小结</h3>

<p>基于此, 我们可以使用 pm2 运行 js, java进程了, 那么其他进程是不是也可以呢, 答案是, 当然可以.<br/>
放开脑洞, 我们可以用pm2运行tomcat, spring-boot应用, node koa应用, node express应用, python进程, go进程, natapp 网络隧道进程等等需要挂起 到后台运行的应用进程, 简直不要太棒!</p>

<h3 id="toc_5">如何启动</h3>

<p>很简单, 只需要:</p>

<pre><code class="language-shell">pm2 start json-config-file.json
</code></pre>

<h2 id="toc_6">结论</h2>

<p>至此, 我们可以很开心的用pm2运行各种程序了, 并基于pm2提供的方便的功能, 查看进程的事实情况, 下一节, 我们将讨论如何利用 pm2的 生态系统文件 -&gt; Ecosystem File 来进行应用的自动更新和部署以及不停机发布.</p>

<h2 id="toc_7">参考资料</h2>

<p><a href="https://www.ddhigh.com/2017/07/31/spring-boot-pm2.html">https://www.ddhigh.com/2017/07/31/spring-boot-pm2.html</a><br/>
<a href="https://github.com/daggerok/pm2-java-spring-boot/blob/master/process.json">https://github.com/daggerok/pm2-java-spring-boot/blob/master/process.json</a><br/>
<a href="https://pm2.io/doc/en/runtime/reference/ecosystem-file/#apps-options">https://pm2.io/doc/en/runtime/reference/ecosystem-file/#apps-options</a></p>


		</div>

		

	</article>
 
	<article>
		 <header>
		  	<h1 class="entry-title"><a href="15408703788547.html">一篇文章搞定 centos7 下安装 nvm和node</a></h1>
			<p class="meta"><time datetime="2018-10-30T11:32:58+08:00" 
			pubdate data-updated="true">2018/10/30</time></p>
		 </header>
	  	<div class="entry-content">
		  	
		  	<ul>
<li>
<a href="#toc_0">在github中搜索nvm</a>
</li>
<li>
<a href="#toc_1">进入项目</a>
</li>
<li>
<a href="#toc_2">安装nvm</a>
<ul>
<li>
<a href="#toc_3">配置环境变量</a>
</li>
</ul>
</li>
<li>
<a href="#toc_4">使用 nvm 安装 node</a>
<ul>
<li>
<ul>
<li>
<a href="#toc_5">查询nvm管理的本地node版本</a>
</li>
<li>
<a href="#toc_6">查询远程可供安装的nvm管理的node版本</a>
</li>
<li>
<a href="#toc_7">安装最新的LTS版本</a>
</li>
</ul>
</li>
</ul>
</li>
<li>
<a href="#toc_8">安装完成</a>
</li>
</ul>


<h2 id="toc_0">在github中搜索nvm</h2>

<p><img src="media/15408703788547/15408704430866.jpg" alt="" style="width:730px;"/></p>

<h2 id="toc_1">进入项目</h2>

<p>在项目的readme.md中, 就有很详细的安装过程了.<br/>
<img src="media/15408703788547/15408705766395.jpg" alt="" style="width:943px;"/></p>

<h2 id="toc_2">安装nvm</h2>

<pre><code class="language-shell">curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
</code></pre>

<h3 id="toc_3">配置环境变量</h3>

<p>将如下代码加入到你的shell配置文件中(一般这些文件是:<br/>
~/.bash_profile, ~/.zshrc, ~/.profile, or ~/.bashrc)</p>

<pre><code class="language-shell">export NVM_DIR=&quot;${XDG_CONFIG_HOME/:-$HOME/.}nvm&quot;
[ -s &quot;$NVM_DIR/nvm.sh&quot; ] &amp;&amp; \. &quot;$NVM_DIR/nvm.sh&quot; # This loads nvm
</code></pre>

<h2 id="toc_4">使用 nvm 安装 node</h2>

<p>这就很简单了我们先</p>

<h4 id="toc_5">查询nvm管理的本地node版本</h4>

<pre><code class="language-shell">nvm list
</code></pre>

<p><img src="media/15408703788547/15408715171278.jpg" alt=""/><br/>
发现什么都没装</p>

<h4 id="toc_6">查询远程可供安装的nvm管理的node版本</h4>

<pre><code class="language-shell">nvm ls-remote
</code></pre>

<p><img src="media/15408703788547/15408716254036.jpg" alt=""/><br/>
结果我们发现好大一坨, 没关系, 我们只要选用最新的LTS版本即可<br/>
这里我们选用v8.12.0</p>

<h4 id="toc_7">安装最新的LTS版本</h4>

<pre><code class="language-shell">nvm install v8.12.0
</code></pre>

<p><img src="media/15408703788547/15408717009392.jpg" alt=""/></p>

<h2 id="toc_8">安装完成</h2>

<p>至此安装已经结束了, 在命令行输入node, 尝试一下最新的LTS版本的node吧.</p>


		</div>

		

	</article>
 
	<article>
		 <header>
		  	<h1 class="entry-title"><a href="15390848111879.html">koa-cache-control 中间件使用详解</a></h1>
			<p class="meta"><time datetime="2018-10-09T19:33:31+08:00" 
			pubdate data-updated="true">2018/10/9</time></p>
		 </header>
	  	<div class="entry-content">
		  	
		  	<ul>
<li>
<a href="#toc_0">什么是koa-cache-control</a>
</li>
<li>
<a href="#toc_1">为什么使用koa-cache-control</a>
</li>
<li>
<a href="#toc_2">如何安装</a>
</li>
<li>
<a href="#toc_3">使用示例</a>
</li>
<li>
<a href="#toc_4">现实demo</a>
</li>
</ul>


<h2 id="toc_0">什么是koa-cache-control</h2>

<blockquote>
<p>A simple method for managing cache control headers from your application. It also tries to provide a simple set of rules for common use cases such as setting &#39;max-age=0&#39; when &#39;no-cache&#39; is present by default.<br/>
中文: 提供简单的方式来管理 cache control 头信息, 也提供了几个简单的配置规则, 例如 当指定 &#39;no-cache&#39; 的时候设置&#39;max-age=0&#39;.</p>
</blockquote>

<h2 id="toc_1">为什么使用koa-cache-control</h2>

<p>要了解为什么要使用cache-control我们要先了解什么是 cache<br/>
具体可以参考: </p>

<ul>
<li><a href="https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=zh-cn">https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=zh-cn</a></li>
<li><a href="https://segmentfault.com/a/1190000005704489?utm_source=caibaojian.com">https://segmentfault.com/a/1190000005704489?utm_source=caibaojian.com</a></li>
</ul>

<p>接下来我们说为什么koa-cache-control中间件, 原因很简单, 因为这样更简单, 更高效, 更方便.</p>

<h2 id="toc_2">如何安装</h2>

<p><code>$ npm install koa-cache-control</code></p>

<h2 id="toc_3">使用示例</h2>

<pre><code class="language-javascript">const Koa = require(&#39;koa&#39;)
const morgan = require(&#39;koa-morgan&#39;)
const path = require(&#39;path&#39;);
const static = require(&#39;koa-static&#39;)
const fs = require(&#39;fs&#39;)
var cacheControl = require(&#39;koa-cache-control&#39;);

const app = new Koa();

app.use(cacheControl({
  maxAge: 86400
}));

// logger
app.use(morgan(&#39;:remote-addr - :remote-user [:date[clf]] &quot;:method :url HTTP/:http-version&quot; :status :res[content-length] :response-time ms&#39;));

// static assets
app.use(static(path.resolve(__dirname, &#39;./dist&#39;)));

//异步读取文件的形式
app.use(async (ctx, next) =&gt; {
  ctx.type = &#39;html&#39;;
  ctx.body = await fs.createReadStream(path.resolve(__dirname, &#39;./dist/index.html&#39;));
});

module.exports = app;
</code></pre>

<h2 id="toc_4">现实demo</h2>

<p>我们线上的知识库测试服务器解决缓存加载问题, 的就是 koa-cache-control 来支持的<br/>
访问地址: <a href="http://120.79.79.6:9000/">http://120.79.79.6:9000/</a></p>


		</div>

		

	</article>
 
	<article>
		 <header>
		  	<h1 class="entry-title"><a href="15390839723979.html">koa-static 中间件使用详解</a></h1>
			<p class="meta"><time datetime="2018-10-09T19:19:32+08:00" 
			pubdate data-updated="true">2018/10/9</time></p>
		 </header>
	  	<div class="entry-content">
		  	
		  	<ul>
<li>
<a href="#toc_0">什么是koa-static</a>
</li>
<li>
<a href="#toc_1">为什么使用koa-static</a>
</li>
<li>
<a href="#toc_2">如何安装</a>
</li>
<li>
<a href="#toc_3">使用示例</a>
</li>
<li>
<a href="#toc_4">现实demo</a>
</li>
</ul>


<h2 id="toc_0">什么是koa-static</h2>

<blockquote>
<p>Koa static file serving middleware, wrapper for koa-send.<br/>
中文: koa static 是一个文件服务中间件, 可以提供静态资源文件的访问支持, 基于 koa-send来实现.</p>
</blockquote>

<h2 id="toc_1">为什么使用koa-static</h2>

<blockquote>
<p>因为我们如果想要提供静态资源, 直接使用 koa 是不支持的, 需要编程来实现, 具体如何实现可以参考: <a href="https://chenshenhai.github.io/koa2-note/note/static/server.html">https://chenshenhai.github.io/koa2-note/note/static/server.html</a><br/>
而更简便的方法是使用业界已经开发好的开源中间件 -&gt; koa-static</p>
</blockquote>

<h2 id="toc_2">如何安装</h2>

<p><code>$ npm install koa-static</code></p>

<h2 id="toc_3">使用示例</h2>

<pre><code class="language-javascript">const serve = require(&#39;koa-static&#39;);
const Koa = require(&#39;koa&#39;);
const app = new Koa();
 
// $ GET /package.json
app.use(serve(&#39;.&#39;));
 
// $ GET /hello.txt
app.use(serve(&#39;test/fixtures&#39;));
 
// or use absolute paths
app.use(serve(__dirname + &#39;/test/fixtures&#39;));
 
app.listen(3000);
 
console.log(&#39;listening on port 3000&#39;);
</code></pre>

<h2 id="toc_4">现实demo</h2>

<p>我们线上的知识库测试服务器使用的就是 koa-static 来支持的<br/>
访问地址: <a href="http://120.79.79.6:9000/">http://120.79.79.6:9000/</a></p>


		</div>

		

	</article>
 
	<article>
		 <header>
		  	<h1 class="entry-title"><a href="15389634104231.html">PM2使用详解</a></h1>
			<p class="meta"><time datetime="2018-10-08T09:50:10+08:00" 
			pubdate data-updated="true">2018/10/8</time></p>
		 </header>
	  	<div class="entry-content">
		  	
		  	<ul>
<li>
<a href="#toc_0">什么是PM2</a>
</li>
<li>
<a href="#toc_1">为什么使用PM2</a>
</li>
<li>
<a href="#toc_2">PM2的主要特性</a>
</li>
<li>
<a href="#toc_3">如何安装</a>
</li>
<li>
<a href="#toc_4">如何部署应用</a>
</li>
<li>
<a href="#toc_5">设置pm2开机启动</a>
</li>
<li>
<a href="#toc_6">调整pm2运行的应用后, 保存到开机启动</a>
</li>
<li>
<a href="#toc_7">其他常用命令(以知识库项目为例)</a>
</li>
<li>
<a href="#toc_8">使用效果示例</a>
</li>
</ul>


<h2 id="toc_0">什么是PM2</h2>

<blockquote>
<p>pm2是一个进程管理工具,可以用它来管理你的node进程，并查看node进程的状态，当然也支持性能监控，进程守护，负载均衡等功能。</p>
</blockquote>

<h2 id="toc_1">为什么使用PM2</h2>

<blockquote>
<p>如果直接通过node app来启动，如果报错了可能直接停在整个运行，supervisor感觉只是拿来用作开发环境的。再网上找到pm2.目前似乎最常见的线上部署nodejs项目的有forever,pm2这两种,今天我们就来讲解PM2的使用</p>
</blockquote>

<h2 id="toc_2">PM2的主要特性</h2>

<ol>
<li>内建负载均衡（使用Node cluster 集群模块）</li>
<li>后台运行</li>
<li>0秒停机重载，我理解大概意思是维护升级的时候不需要停机.</li>
<li>具有Ubuntu和CentOS 的启动脚本</li>
<li>停止不稳定的进程（避免无限循环）</li>
<li>控制台检测</li>
<li>提供 HTTP API</li>
<li>远程控制和实时的接口API ( Nodejs 模块,允许和PM2进程管理器交互 )</li>
</ol>

<h2 id="toc_3">如何安装</h2>

<p><code>npm install -g pm2</code></p>

<h2 id="toc_4">如何部署应用</h2>

<p><code>pm2 start server.js --name=knowledge -i max</code></p>

<h2 id="toc_5">设置pm2开机启动</h2>

<p>运行 </p>

<pre><code class="language-shell">pm2 startup
</code></pre>

<p>即在/etc/init.d/目录下生成pm2-root的启动脚本，且自动将pm2-root设为服务。</p>

<h2 id="toc_6">调整pm2运行的应用后, 保存到开机启动</h2>

<p>运行</p>

<pre><code class="language-shell">pm2 save
</code></pre>

<p>会将当前pm2所运行的应用保存在/root/.pm2/dump.pm2下，当开机重启时，运行pm2-root服务脚本，并且到/root/.pm2/dump.pm2下读取应用并启动。</p>

<h2 id="toc_7">其他常用命令(以知识库项目为例)</h2>

<p><img src="media/15389634104231/15389967084289.jpg" alt=""/></p>

<h2 id="toc_8">使用效果示例</h2>

<p><img src="media/15389634104231/15390839430311.jpg" alt=""/></p>


		</div>

		

	</article>
  
	<div class="pagination">
	
<a href="archives.html">Blog Archives</a>
	 
	    
	</div>
</div>
 <aside class="sidebar"> 

	<section>
	  <h1>Categories</h1>
	  <ul id="recent_posts">
	  
	      <li class="post">
	        <a href="version-control.html"><strong>version-control&nbsp;(2)</strong></a>
	        
	        
	        
	      </li>
	  
	      <li class="post">
	        <a href="shell.html"><strong>shell&nbsp;(1)</strong></a>
	        
	        
	        
	      </li>
	  
	      <li class="post">
	        <a href="back-end.html"><strong>back-end&nbsp;(4)</strong></a>
	        
	        
	        
	      </li>
	  
	      <li class="post">
	        <a href="front-end.html"><strong>front-end&nbsp;(5)</strong></a>
	        
	        
	        
	      </li>
	  
	      <li class="post">
	        <a href="version-control-1.html"><strong>version-control&nbsp;(1)</strong></a>
	        
	        
	        
	      </li>
	  
	      <li class="post">
	        <a href="other.html"><strong>other&nbsp;(2)</strong></a>
	        
	        
	        
	      </li>
	   
	  </ul>
	</section>
	<section>
	  <h1>Recent Posts</h1>
	  <ul id="recent_posts">
	  
	      
		      <li class="post">
		        <a href="15413898294420.html">RESTful API 最佳实践</a>
		      </li>
	     
	  
	      
		      <li class="post">
		        <a href="15411425055347.html">LZH-DEV-GROUP Git Workflow 实践详解</a>
		      </li>
	     
	  
	      
		      <li class="post">
		        <a href="15410718240579.html">如何使用PM2进程管理器, 守护java进程</a>
		      </li>
	     
	  
	      
		      <li class="post">
		        <a href="15408811446857.html">一篇文章搞定 centos7 上的 mysql 安装</a>
		      </li>
	     
	  
	      
		      <li class="post">
		        <a href="15408703788547.html">一篇文章搞定 centos7 下安装 nvm和node</a>
		      </li>
	     
	  
	      
	  
	      
	  
	      
	  
	      
	  
	      
	  
	      
	  
	      
	  
	      
	  
	      
	  
	      
	   
	  </ul>
	</section>
	
</aside> </div></div>
  <footer role="contentinfo"><p>
  Copyright &copy; 2014 -  -
  <span class="credit">Powered by <a target="_blank" href="http://www.mweb.im">MWeb</a> &nbsp;&nbsp; Theme by <a href="http://octopress.org">Octopress</a></span>
</p>

</footer>

  
    




</body>
</html>